package com.yfp.machine.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONObject;
import com.yfp.common.core.constant.DbConstants;
import com.yfp.common.core.constant.EmqxConstants;
import com.yfp.common.core.exception.ServiceException;
import com.yfp.common.security.utils.SecurityUtils;
import com.yfp.emqx.MqttSendClient;
import com.yfp.machine.domain.ApkVersion;
import com.yfp.machine.domain.Machine;
import com.yfp.machine.domain.MachineApk;
import com.yfp.machine.domain.VersionPushRecord;
import com.yfp.machine.domain.vo.ApkVersionPushVo;
import com.yfp.machine.mapper.ApkVersionMapper;
import com.yfp.machine.service.ApkVersionService;
import com.yfp.machine.service.MachineApkService;
import com.yfp.machine.service.MachineService;
import com.yfp.machine.service.VersionPushRecordService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.UUID;


/**
 * (ApkVersion)表服务实现类
 *
 * 
 * @since 2023-12-14 15:00:35
 */
@Service("apkVersionService")
@Slf4j
public class ApkVersionServiceImpl implements ApkVersionService {
    @Resource
    private ApkVersionMapper apkVersionMapper;

    @Resource
    private MachineApkService machineApkService;
    @Resource
    private VersionPushRecordService versionPushRecordService;

    @Resource
    MqttSendClient mqttSendClient;

    @Resource
    MachineService machineService;


    /**
     * 通过ID查询单条数据
     *
     * @param versionNo 主键
     * @return 实例对象
     */
    @Override
    public ApkVersion queryById(String versionNo) {
        return this.apkVersionMapper.queryById(versionNo);
    }

    /**
     * 分页查询
     *
     * @param apkVersion 筛选条件
     * @return 查询结果
     */
    @Override
    public List<ApkVersion> queryApkVersion(ApkVersion apkVersion) {
        return this.apkVersionMapper.queryAll(apkVersion);
    }

    /**
     * 新增数据
     *
     * @param apkVersion 实例对象
     * @return 实例对象
     */
    @Override
    public ApkVersion insert(ApkVersion apkVersion) {
        ApkVersion apkVersion1 = new ApkVersion();
        apkVersion1.setVersionNo(apkVersion.getVersionNo());
        long count = this.apkVersionMapper.count(apkVersion1);
        if (count > 0) throw new ServiceException("APK版本号已存在,请核查");
        this.apkVersionMapper.insert(apkVersion);
        return apkVersion;
    }

    /**
     * 修改数据
     *
     * @param apkVersion 实例对象
     * @return 实例对象
     */
    @Override
    public ApkVersion update(ApkVersion apkVersion) {
        this.apkVersionMapper.update(apkVersion);
        return this.queryById(apkVersion.getVersionNo());
    }

    /**
     * 通过主键删除数据
     *
     * @param versionNo 主键
     * @return 是否成功
     */
    @Override
    public boolean deleteById(String versionNo) {
        return this.apkVersionMapper.deleteById(versionNo) > 0;
    }

    @Override
    public List<ApkVersion> findCorrespondingAppVersionByMachineType(Integer machineType, String machineId) {

        ApkVersion apkVersion = new ApkVersion();
        apkVersion.setMachineType(machineType);
        apkVersion.setIsDelete(DbConstants.FALSE);
        List<ApkVersion> apkVersions = this.apkVersionMapper.queryAllByApkVersion(apkVersion);
        //内部版本比较 展示
        MachineApk machineApk = machineApkService.queryById(machineId);
        if (ObjectUtil.isNotNull(machineApk)){
            return apkVersions.stream().filter(apkVer -> machineApk.getInnerVersionNo() > apkVer.getInnerVersionNo()).toList();
        }
        return apkVersions;
    }

    @Override
    public boolean pushApkVersion(ApkVersionPushVo apkVersionPushVos) {
        String appVersionNo = apkVersionPushVos.getAppVersionNo();
        List<String> machineIds = apkVersionPushVos.getMachineId();
        //获取apk版本数据
        ApkVersion apkVersion = this.apkVersionMapper.queryById(appVersionNo);

        if (ObjectUtil.isNull(apkVersion)) return false;

        for (String machineId : machineIds) {
            MachineApk machineApk = machineApkService.queryById(machineId);
            if (ObjectUtil.isNotNull(machineApk) && machineApk.getInnerVersionNo() > apkVersion.getInnerVersionNo()){
                throw new ServiceException("当前设备版本号大于该APK版本号,请核查");
            }
            String recordNo = UUID.randomUUID().toString();
            if (pushAPK(machineId, apkVersion, recordNo)) continue;
            //记录
            saveVersionPushRecord(machineId, apkVersion, recordNo);
        }
        apkVersion.setPushStatus(DbConstants.machineCorrelation.PUSHED);
        apkVersion.setPushOper(SecurityUtils.getLoginUser().getSysUser().getNickName());
        apkVersion.setPushTime(new Date());
        this.apkVersionMapper.update(apkVersion);
        return true;
    }

    /**
     * 删除版本
     * @param versionNo
     */
    @Override
    @Transactional
    public void updateIsDelete(String versionNo) {

        this.apkVersionMapper.updateIsDelete(versionNo);

//        // 根据版本号查询使用的设备数量
//        Integer count = machineApkService.getByVersionNo(versionNo);
//        if (count == 0) {
//            this.apkVersionMapper.updateIsDelete(versionNo);
//            return;
//        }
//        throw new ServiceException("删除失败，该版本仍在被使用");
    }

    /**
     * 推送apk
     *
     * @param machineId  机器id
     * @param apkVersion apk版本
     * @return boolean
     */
    private boolean pushAPK(String machineId, ApkVersion apkVersion,String recordNo ) {
        JSONObject msgData = new JSONObject();
        msgData.set(EmqxConstants.MachineApkType.TOPIC_PUSH_APK_URL, apkVersion.getUrl());
        msgData.set(EmqxConstants.MachineApkType.TOPIC_PUSH_VERSION_CODE, apkVersion.getInnerVersionNo());
        msgData.set(EmqxConstants.MachineApkType.TOPIC_PUSH_VERSION_NAME, apkVersion.getVersionName());
        JSONObject pushObj = new JSONObject();
        pushObj.set(EmqxConstants.TOPIC_PUSH_MSG_TYPE, EmqxConstants.TOPIC_PUSH_APK);
        pushObj.set(EmqxConstants.TOPIC_PUSH_TIME, DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
        pushObj.set(EmqxConstants.TOPIC_PUSH_RECORD_NO, recordNo);
        pushObj.set("msgData", msgData);

        try {
            mqttSendClient.publish(false, machineId, pushObj.toString());
        } catch (Exception e) {
            log.error("设备ID:{},APK版本推送失败,APK信息:{}", machineId, apkVersion, e);
            return true;
        }
        log.info("设备ID:{},APK版本推送成功,APK信息:{}", machineId, pushObj);
        return false;
    }

    @NotNull
    private void saveVersionPushRecord(String machineId, ApkVersion apkVersion,String recordNo) {
        Machine machine = this.machineService.getMachineById(machineId);

        VersionPushRecord versionPushRecord = new VersionPushRecord();
        versionPushRecord.setInnerVersionNo(apkVersion.getInnerVersionNo());
        versionPushRecord.setPushTime(new Date());
        versionPushRecord.setRecordNo(recordNo);
        versionPushRecord.setVersionNo(apkVersion.getVersionNo());
        versionPushRecord.setVersionName(apkVersion.getVersionName());
        versionPushRecord.setMachineId(machineId);
        versionPushRecord.setUrl(apkVersion.getUrl());
        versionPushRecord.setSize(apkVersion.getSize());
        versionPushRecord.setPushTime(new Date());
        if (ObjectUtil.isNotNull(machine)) versionPushRecord.setMachineType(machine.getMachineType());
        versionPushRecordService.insert(versionPushRecord);
    }
}
